#include <ArduinoJson.h>
#include <stdio.h>

#include "webapi_http_utils.h"
#include "webapi_amap_weather.h"

namespace webapi {

#define AMAP_WEATHER_URL "http://restapi.amap.com/v3/weather/weatherInfo"

#define GET_JSON_FIELD(response, field, doc, type) \
  response.field = doc[#field].as<type>();         \
  Serial.printf("Parsed json[%s]: ", #field);      \
  Serial.println(response.field);

bool AmapWeatherService::QueryRealtimeWeather(AmapRealtimeWeather& response,
                                              int adcode) {
  char rtwURL[128] = "";
  snprintf(rtwURL, sizeof(rtwURL),
           AMAP_WEATHER_URL "?key=%s&city=%d&extensions=base",
           this->GetAmapApiKey(), adcode);

  String content;
  if (!HttpGet(rtwURL, content)) {
    Serial.printf("Request to %s FAILED!\r\n", rtwURL);
    return false;
  }

  JsonDocument doc;
  if (auto error = deserializeJson(doc, content)) {
    Serial.printf("Parse response from %s FAILED!\r\n", rtwURL);
    return false;
  }

  GET_JSON_FIELD(response, status, doc, int);
  GET_JSON_FIELD(response, info, doc, const char*);
  GET_JSON_FIELD(response, infocode, doc, int);

  auto live = doc["lives"][0];
  GET_JSON_FIELD(response, adcode, live, int);
  GET_JSON_FIELD(response, city, live, const char*);
  GET_JSON_FIELD(response, province, live, const char*);
  GET_JSON_FIELD(response, reporttime, live, const char*);
  GET_JSON_FIELD(response, weather, live, const char*);
  GET_JSON_FIELD(response, temperature, live, const char*);
  GET_JSON_FIELD(response, humidity, live, const char*);
  GET_JSON_FIELD(response, winddirection, live, const char*);
  GET_JSON_FIELD(response, windpower, live, const char*);
  return true;
}

bool AmapWeatherService::QueryForecastWeather(AmapForecastWeather& response,
                                              int adcode) {
  char rtwURL[128] = "";
  snprintf(rtwURL, sizeof(rtwURL),
           AMAP_WEATHER_URL "?key=%s&city=%d&extensions=all",
           this->GetAmapApiKey(), adcode);

  String content;
  if (!HttpGet(rtwURL, content)) {
    Serial.printf("Request to %s FAILED!\r\n", rtwURL);
    return false;
  }

  JsonDocument doc;
  if (auto error = deserializeJson(doc, content)) {
    Serial.printf("Parse response from %s FAILED!\r\n", rtwURL);
    return false;
  }

  GET_JSON_FIELD(response, status, doc, int);
  GET_JSON_FIELD(response, info, doc, const char*);
  GET_JSON_FIELD(response, infocode, doc, int);

  auto forecast = doc["forecasts"][0];
  GET_JSON_FIELD(response, adcode, forecast, int);
  GET_JSON_FIELD(response, city, forecast, const char*);
  GET_JSON_FIELD(response, province, forecast, const char*);
  GET_JSON_FIELD(response, reporttime, forecast, const char*);

  auto casts = forecast["casts"];
  int size = AmapForecastWeather::kDays;
  if (casts.size() < size) {
    size = casts.size();
  }
  response.count = size;
  for (int i = 0; i < size; i++) {
    auto cast = casts[i];
    GET_JSON_FIELD(response.casts[i], date, cast, const char*);
    GET_JSON_FIELD(response.casts[i], week, cast, const char*);
    GET_JSON_FIELD(response.casts[i], dayweather, cast, const char*);
    GET_JSON_FIELD(response.casts[i], nightweather, cast, const char*);
    GET_JSON_FIELD(response.casts[i], daytemp, cast, const char*);
    GET_JSON_FIELD(response.casts[i], nighttemp, cast, const char*);
    GET_JSON_FIELD(response.casts[i], daywind, cast, const char*);
    GET_JSON_FIELD(response.casts[i], nightwind, cast, const char*);
    GET_JSON_FIELD(response.casts[i], daypower, cast, const char*);
    GET_JSON_FIELD(response.casts[i], nightpower, cast, const char*);
  }
  return true;
}

}  // namespace webapi
